fix: global concurrency cap for hook-triggered indexers - #160
Open
rajkumarsakthivel wants to merge 5 commits into
Open
fix: global concurrency cap for hook-triggered indexers#160rajkumarsakthivel wants to merge 5 commits into
rajkumarsakthivel wants to merge 5 commits into
Conversation
Warm zinc-black palette, indigo accents, Inter+Outfit typography. Massive 94% number as hero focal point, trust-strip with editor logos, vertical numbered capabilities, horizontal benchmark stats, and comparison table with green "Best" pill.
Git hooks installed by CCE fire in all worktrees (shared .git/hooks/), and the old hook spawned unbounded background indexers. With N worktrees this produced N detached cce-index processes (observed: 36 at ~1.85GB each, ~66GB total on a 96GB machine). Three changes: - Global machine-wide lock via mkdir (POSIX portable, works on macOS without flock). At most one hook-triggered indexer runs at a time. - Skip ephemeral worktree paths (/tmp/*, .claude/worktrees/*) since those trees are deleted minutes later. - nice -n 10 so indexing never competes with foreground work. Also fixes: - install_hooks() now resolves through git common dir so hooks install correctly from inside a worktree. - cce init/upgrade replaces old hook blocks with the new guarded version instead of silently skipping when the marker is present. - Uninstall handles multi-line hook blocks (start/end markers).
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses runaway resource usage from hook-triggered cce index when Git worktrees share a common hooks directory, by making hook installation worktree-aware and adding guardrails to the generated hook script.
Changes:
- Adds a guarded, background hook script that attempts to serialize hook-triggered indexing via a global lock and deprioritizes indexing with
nice. - Resolves hooks installation through
git rev-parse --git-common-dirso installing from within a worktree writes to the effective hooks directory. - Updates hook-uninstall stripping logic to support the new multi-line hook block format (marker + end-marker), while remaining backward-compatible with the legacy single-line format.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/context_engine/indexer/git_hooks.py | Generates new guarded hook script and installs hooks into the correct common hooks dir for worktrees; adds upgrade behavior when an existing marker is found. |
| src/context_engine/cli.py | Updates uninstall hook-block stripping to handle the new multi-line hook block format. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+63
to
+67
| # Build the ephemeral-path skip check as shell conditions. | ||
| skip_checks = " || ".join( | ||
| f'case "$PWD" in *{shlex.quote(m)}*) true;; *) false;; esac' | ||
| for m in _EPHEMERAL_PATH_MARKERS | ||
| ) |
Comment on lines
+12
to
+16
| # Max concurrent hook-triggered indexers machine-wide. The hook script | ||
| # uses a global lock file (not per-project) so worktrees sharing | ||
| # .git/hooks/ don't each spawn their own unbounded indexer. See #159. | ||
| _MAX_CONCURRENT_INDEXERS = 2 | ||
|
|
Comment on lines
+2409
to
+2412
| # Old format (no end marker): skip just the one line after marker | ||
| if not any(HOOK_END_MARKER in ln for ln in lines): | ||
| inside_block = False | ||
| continue |
Comment on lines
+161
to
+165
| marker_idx = existing.index(HOOK_MARKER) | ||
| prefix = existing[:marker_idx].rstrip() | ||
| new_content = prefix + ("\n\n" if prefix else "#!/bin/sh\n\n") + script | ||
| hook_path.write_text(new_content, encoding="utf-8") | ||
| hook_path.chmod(hook_path.stat().st_mode | stat.S_IEXEC) |
- Remove shlex.quote from case glob patterns (broke ephemeral path matching) - Remove unused _MAX_CONCURRENT_INDEXERS constant - Fix _strip_cce_git_hook_block to detect end marker only after start marker - Fix reinstall to preserve user content after the CCE block
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #159. Git hooks fire in all worktrees (shared
.git/hooks/), and the old hook spawned unbounded background indexers. With N worktrees this produced N detachedcce indexprocesses.mkdir(POSIX portable, works on macOS withoutflock). At most one hook-triggered indexer runs at a time. Stale locks are reclaimed when the owner PID is dead./tmp/*,.claude/worktrees/*) since agent-created throwaway trees are deleted minutes later.nice -n 10so indexing never competes with foreground work.install_hooks()resolves throughgit rev-parse --git-common-dirso hooks install correctly from inside a worktree.cce initreplaces old single-line hook blocks with the new guarded version instead of silently skipping when the marker is present.